From d47772f002efdb1d88b61d8176ea432e7a8b5106 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Sat, 24 Oct 2009 11:48:39 +0200 Subject: [PATCH] Create a proper subclass of GdkScreen: GdkScreenQuartz --- gdk/quartz/Makefile.am | 1 + gdk/quartz/gdkdisplay-quartz.c | 8 +- gdk/quartz/gdkprivate-quartz.h | 3 - gdk/quartz/gdkscreen-quartz.c | 302 +++++++++++++++++---------------- gdk/quartz/gdkscreen-quartz.h | 62 +++++++ 5 files changed, 222 insertions(+), 154 deletions(-) create mode 100644 gdk/quartz/gdkscreen-quartz.h diff --git a/gdk/quartz/Makefile.am b/gdk/quartz/Makefile.am index 2c3e621c59..a5721b1c3e 100644 --- a/gdk/quartz/Makefile.am +++ b/gdk/quartz/Makefile.am @@ -46,6 +46,7 @@ libgdk_quartz_la_SOURCES = \ gdkproperty-quartz.c \ gdkquartz.h \ gdkscreen-quartz.c \ + gdkscreen-quartz.h \ gdkselection-quartz.c \ gdkspawn-quartz.c \ gdktestutils-quartz.c \ diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c index fd38da1312..957bb43bef 100644 --- a/gdk/quartz/gdkdisplay-quartz.c +++ b/gdk/quartz/gdkdisplay-quartz.c @@ -22,6 +22,7 @@ #include "gdk.h" #include "gdkprivate-quartz.h" +#include "gdkscreen-quartz.h" GdkWindow * gdk_display_get_default_group (GdkDisplay *display) @@ -51,13 +52,14 @@ gdk_display_open (const gchar *display_name) [NSApplication sharedApplication]; _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL); - _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL); + + _gdk_visual_init (); + + _gdk_screen = _gdk_screen_quartz_new (); nsscreen = [[NSScreen screens] objectAtIndex:0]; gdk_screen_set_resolution (_gdk_screen, 72.0 * [nsscreen userSpaceScaleFactor]); - _gdk_visual_init (); - _gdk_quartz_screen_init (); _gdk_windowing_window_init (); _gdk_events_init (); diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index 86db886fbc..52834b36d5 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -152,9 +152,6 @@ void _gdk_quartz_window_debug_highlight (GdkWindow *window, void _gdk_quartz_window_set_needs_display_in_rect (GdkWindow *window, GdkRectangle *rect); -/* Screen */ -void _gdk_quartz_screen_init (void); - /* Events */ typedef enum { GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c index 41d51c791b..4c08109500 100644 --- a/gdk/quartz/gdkscreen-quartz.c +++ b/gdk/quartz/gdkscreen-quartz.c @@ -20,20 +20,89 @@ #include "config.h" #include "gdk.h" +#include "gdkscreen-quartz.h" #include "gdkprivate-quartz.h" -/* FIXME: If we want to do it properly, this should be stored - * in a proper GdkScreen subclass. - */ -static GdkColormap *default_colormap = NULL; -static int n_screens = 0; -static GdkRectangle *screen_rects = NULL; -static guint screen_changed_id = 0; +static void gdk_screen_quartz_dispose (GObject *object); +static void gdk_screen_quartz_finalize (GObject *object); +static void gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen); + +static void display_reconfiguration_callback (CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags, + void *userInfo); + +G_DEFINE_TYPE (GdkScreenQuartz, _gdk_screen_quartz, GDK_TYPE_SCREEN); + +static void +_gdk_screen_quartz_class_init (GdkScreenQuartzClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gdk_screen_quartz_dispose; + object_class->finalize = gdk_screen_quartz_finalize; +} + +static void +_gdk_screen_quartz_init (GdkScreenQuartz *screen_quartz) +{ + GdkScreen *screen = GDK_SCREEN (screen_quartz); + + gdk_screen_set_default_colormap (screen, + gdk_screen_get_system_colormap (screen)); + + gdk_screen_quartz_calculate_layout (screen_quartz); + + CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback, + screen); +} + +static void +gdk_screen_quartz_dispose (GObject *object) +{ + GdkScreenQuartz *screen = GDK_SCREEN_QUARTZ (object); + + if (screen->default_colormap) + { + g_object_unref (screen->default_colormap); + screen->default_colormap = NULL; + } + if (screen->screen_changed_id) + { + g_source_remove (screen->screen_changed_id); + screen->screen_changed_id = 0; + } + + CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback, + screen); + + G_OBJECT_CLASS (_gdk_screen_quartz_parent_class)->dispose (object); +} static void -screen_rects_init (void) +gdk_screen_quartz_screen_rects_free (GdkScreenQuartz *screen) +{ + screen->n_screens = 0; + + if (screen->screen_rects) + { + g_free (screen->screen_rects); + screen->screen_rects = NULL; + } +} + +static void +gdk_screen_quartz_finalize (GObject *object) +{ + GdkScreenQuartz *screen = GDK_SCREEN_QUARTZ (object); + + gdk_screen_quartz_screen_rects_free (screen); +} + + +static void +gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen) { NSArray *array; NSRect largest_rect; @@ -41,14 +110,29 @@ screen_rects_init (void) GDK_QUARTZ_ALLOC_POOL; - array = [NSScreen screens]; + gdk_screen_quartz_screen_rects_free (screen); - n_screens = [array count]; - screen_rects = g_new0 (GdkRectangle, n_screens); + array = [NSScreen screens]; - /* FIXME: as stated above the get_width() and get_height() functions - * in this file, we only support horizontal screen layouts for now. + /* FIXME: For now we only support screen layouts where the screens are laid + * out horizontally. Mac OS X also supports laying out the screens vertically + * and the screens having "non-standard" offsets from eachother. In the + * future we need a much more sophiscated algorithm to translate these + * layouts to GDK coordinate space and GDK screen layout. */ + screen->width = 0; + screen->height = 0; + + for (i = 0; i < [array count]; i++) + { + NSRect rect = [[array objectAtIndex:i] frame]; + + screen->width += rect.size.width; + screen->height = MAX (screen->height, rect.size.height); + } + + screen->n_screens = [array count]; + screen->screen_rects = g_new0 (GdkRectangle, screen->n_screens); /* Find the monitor with the largest height. All monitors should be * offset to this one in the GDK screen space instead of offset to @@ -63,7 +147,7 @@ screen_rects_init (void) largest_rect = [[array objectAtIndex:i] frame]; } - for (i = 0; i < n_screens; i++) + for (i = 0; i < screen->n_screens; i++) { NSScreen *nsscreen; NSRect rect; @@ -71,57 +155,54 @@ screen_rects_init (void) nsscreen = [array objectAtIndex:i]; rect = [nsscreen frame]; - screen_rects[i].x = rect.origin.x; - screen_rects[i].width = rect.size.width; - screen_rects[i].height = rect.size.height; + screen->screen_rects[i].x = rect.origin.x; + screen->screen_rects[i].width = rect.size.width; + screen->screen_rects[i].height = rect.size.height; if (largest_rect.size.height - rect.size.height == 0) - screen_rects[i].y = 0; + screen->screen_rects[i].y = 0; else - screen_rects[i].y = largest_rect.size.height - rect.size.height + largest_rect.origin.y; + screen->screen_rects[i].y = largest_rect.size.height - rect.size.height + largest_rect.origin.y; } GDK_QUARTZ_RELEASE_POOL; } + static void -screen_rects_free (void) +process_display_reconfiguration (GdkScreenQuartz *screen) { - n_screens = 0; + int width, height; - g_free (screen_rects); - screen_rects = NULL; -} + width = gdk_screen_get_width (GDK_SCREEN (screen)); + height = gdk_screen_get_height (GDK_SCREEN (screen)); + gdk_screen_quartz_calculate_layout (GDK_SCREEN_QUARTZ (screen)); -static void -process_display_reconfiguration (void) -{ - screen_rects_free (); - screen_rects_init (); - - /* FIXME: We should only emit this when the size of screen really - * has changed. We need to start bookkeeping width, height once - * we have a proper GdkScreen subclass. - */ - g_signal_emit_by_name (_gdk_screen, "size-changed"); + if (width != gdk_screen_get_width (GDK_SCREEN (screen)) + || height != gdk_screen_get_height (GDK_SCREEN (screen))) + g_signal_emit_by_name (_gdk_screen, "size-changed"); } static gboolean screen_changed_idle (gpointer data) { - process_display_reconfiguration (); + GdkScreenQuartz *screen = data; + + process_display_reconfiguration (data); - screen_changed_id = 0; + screen->screen_changed_id = 0; return FALSE; } static void -screen_changed (CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags, - void *userInfo) +display_reconfiguration_callback (CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags, + void *userInfo) { + GdkScreenQuartz *screen = userInfo; + if (flags & kCGDisplayBeginConfigurationFlag) { /* Ignore the begin configuration signal. */ @@ -137,21 +218,16 @@ screen_changed (CGDirectDisplayID display, * yet, so we delay our refresh into an idle handler. */ - if (!screen_changed_id) - screen_changed_id = gdk_threads_add_idle (screen_changed_idle, NULL); + if (!screen->screen_changed_id) + screen->screen_changed_id = gdk_threads_add_idle (screen_changed_idle, + screen); } } -void -_gdk_quartz_screen_init (void) +GdkScreen * +_gdk_screen_quartz_new (void) { - gdk_screen_set_default_colormap (_gdk_screen, - gdk_screen_get_system_colormap (_gdk_screen)); - - screen_rects_init (); - - CGDisplayRegisterReconfigurationCallback (screen_changed, - _gdk_screen); + return g_object_new (GDK_TYPE_SCREEN_QUARTZ, NULL); } GdkDisplay * @@ -192,7 +268,9 @@ _gdk_windowing_substitute_screen_number (const gchar *display_name, GdkColormap* gdk_screen_get_default_colormap (GdkScreen *screen) { - return default_colormap; + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return GDK_SCREEN_QUARTZ (screen)->default_colormap; } void @@ -204,67 +282,28 @@ gdk_screen_set_default_colormap (GdkScreen *screen, g_return_if_fail (GDK_IS_SCREEN (screen)); g_return_if_fail (GDK_IS_COLORMAP (colormap)); - old_colormap = default_colormap; + old_colormap = GDK_SCREEN_QUARTZ (screen)->default_colormap; - default_colormap = g_object_ref (colormap); + GDK_SCREEN_QUARTZ (screen)->default_colormap = g_object_ref (colormap); if (old_colormap) g_object_unref (old_colormap); } -/* FIXME: note on the get_width() and the get_height() methods. For - * now we only support screen layouts where the screens are laid out - * horizontally. Mac OS X also supports laying out the screens vertically - * and the screens having "non-standard" offsets from eachother. In the - * future we need a much more sophiscated algorithm to translate these - * layouts to GDK coordinate space and GDK screen layout. - */ gint gdk_screen_get_width (GdkScreen *screen) { - int i; - int width; - NSArray *array; - g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); - GDK_QUARTZ_ALLOC_POOL; - array = [NSScreen screens]; - - width = 0; - for (i = 0; i < [array count]; i++) - { - NSRect rect = [[array objectAtIndex:i] frame]; - width += rect.size.width; - } - - GDK_QUARTZ_RELEASE_POOL; - - return width; + return GDK_SCREEN_QUARTZ (screen)->width; } gint gdk_screen_get_height (GdkScreen *screen) { - int i; - int height; - NSArray *array; - g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); - GDK_QUARTZ_ALLOC_POOL; - array = [NSScreen screens]; - - height = 0; - for (i = 0; i < [array count]; i++) - { - NSRect rect = [[array objectAtIndex:i] frame]; - height = MAX (height, rect.size.height); - } - - GDK_QUARTZ_RELEASE_POOL; - - return height; + return GDK_SCREEN_QUARTZ (screen)->height; } static gint @@ -283,79 +322,46 @@ get_mm_from_pixels (NSScreen *screen, int pixels) return (pixels / dpi) * 25.4; } -gint -gdk_screen_get_width_mm (GdkScreen *screen) +static NSScreen * +get_nsscreen_for_monitor (gint monitor_num) { - int i; - gint width; NSArray *array; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + NSScreen *screen; GDK_QUARTZ_ALLOC_POOL; - array = [NSScreen screens]; - width = 0; - for (i = 0; i < [array count]; i++) - { - NSScreen *screen = [array objectAtIndex:i]; - NSRect rect = [screen frame]; - width += get_mm_from_pixels (screen, rect.size.width); - } + array = [NSScreen screens]; + screen = [array objectAtIndex:monitor_num]; GDK_QUARTZ_RELEASE_POOL; - return width; + return screen; } gint -gdk_screen_get_height_mm (GdkScreen *screen) +gdk_screen_get_width_mm (GdkScreen *screen) { - int i; - gint height; - NSArray *array; - g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); - GDK_QUARTZ_ALLOC_POOL; - array = [NSScreen screens]; - - height = 0; - for (i = 0; i < [array count]; i++) - { - NSScreen *screen = [array objectAtIndex:i]; - NSRect rect = [screen frame]; - gint h = get_mm_from_pixels (screen, rect.size.height); - height = MAX (height, h); - } - - GDK_QUARTZ_RELEASE_POOL; - - return height; + return get_mm_from_pixels (get_nsscreen_for_monitor (0), + GDK_SCREEN_QUARTZ (screen)->width); } -int -gdk_screen_get_n_monitors (GdkScreen *screen) +gint +gdk_screen_get_height_mm (GdkScreen *screen) { g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); - return n_screens; + return get_mm_from_pixels (get_nsscreen_for_monitor (0), + GDK_SCREEN_QUARTZ (screen)->height); } -static NSScreen * -get_nsscreen_for_monitor (gint monitor_num) +int +gdk_screen_get_n_monitors (GdkScreen *screen) { - NSArray *array; - NSScreen *screen; - - GDK_QUARTZ_ALLOC_POOL; - - array = [NSScreen screens]; - screen = [array objectAtIndex:monitor_num]; - - GDK_QUARTZ_RELEASE_POOL; + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); - return screen; + return GDK_SCREEN_QUARTZ (screen)->n_screens; } gint @@ -367,7 +373,7 @@ gdk_screen_get_monitor_width_mm (GdkScreen *screen, g_return_val_if_fail (monitor_num >= 0, 0); return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num), - screen_rects[monitor_num].width); + GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num].width); } gint @@ -379,7 +385,7 @@ gdk_screen_get_monitor_height_mm (GdkScreen *screen, g_return_val_if_fail (monitor_num >= 0, 0); return get_mm_from_pixels (get_nsscreen_for_monitor (monitor_num), - screen_rects[monitor_num].height); + GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num].height); } gchar * @@ -399,7 +405,7 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen, g_return_if_fail (monitor_num < gdk_screen_get_n_monitors (screen)); g_return_if_fail (monitor_num >= 0); - *dest = screen_rects[monitor_num]; + *dest = GDK_SCREEN_QUARTZ (screen)->screen_rects[monitor_num]; } gchar * diff --git a/gdk/quartz/gdkscreen-quartz.h b/gdk/quartz/gdkscreen-quartz.h new file mode 100644 index 0000000000..a67401d03f --- /dev/null +++ b/gdk/quartz/gdkscreen-quartz.h @@ -0,0 +1,62 @@ +/* gdkscreen-quartz.h + * + * Copyright (C) 2009 Kristian Rietveld + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GDK_SCREEN_QUARTZ_H__ +#define __GDK_SCREEN_QUARTZ_H__ + +G_BEGIN_DECLS + +typedef struct _GdkScreenQuartz GdkScreenQuartz; +typedef struct _GdkScreenQuartzClass GdkScreenQuartzClass; + +#define GDK_TYPE_SCREEN_QUARTZ (_gdk_screen_quartz_get_type ()) +#define GDK_SCREEN_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartz)) +#define GDK_SCREEN_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartzClass)) +#define GDK_IS_SCREEN_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SCREEN_QUARTZ)) +#define GDK_IS_SCREEN_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SCREEN_QUARTZ)) +#define GDK_SCREEN_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SCREEN_QUARTZ, GdkScreenQuartzClass)) + +struct _GdkScreenQuartz +{ + GdkScreen parent_instance; + + GdkDisplay *display; + GdkColormap *default_colormap; + + gint width; + gint height; + + int n_screens; + GdkRectangle *screen_rects; + + guint screen_changed_id; +}; + +struct _GdkScreenQuartzClass +{ + GdkScreenClass parent_class; +}; + +GType _gdk_screen_quartz_get_type (void); +GdkScreen *_gdk_screen_quartz_new (void); + +G_END_DECLS + +#endif /* _GDK_SCREEN_QUARTZ_H_ */ -- 2.30.2